/* GLUCo - OpenGL Unified Code
 * 
 * Copyright (c) 2007 Pedro Leite.
 * 
 * Written by Pedro Leite, <pedro.leite@gmail.com>
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include "window.h"

#define CHECK_WINDOW(window) {\
	if (!window) {\
		REPORT_ERROR("Invalid window pointer.")\
		return;\
	}\
}\

Window* create_window(const char* title, unsigned int width,
unsigned int height, unsigned int x_pos, unsigned int y_pos, bool fullscreen) {
	Window* window = (Window*) malloc(sizeof(Window));

	if (title) {
		window->title = (char *) calloc(strlen(title) + 1, sizeof(char));
		strcpy(window->title, title);
	} else {
		window->title = 0;
	}

	window->width = width;
	window->height = height;
	window->x_pos = x_pos;
	window->y_pos = y_pos;
	window->fullscreen = fullscreen;
	window->visible = true;

	window->init_func = 0;
	window->display_func = 0;
	window->reshape_func = 0;
	window->keyboard_func = 0;
	window->keyboard_up_func = 0;
	window->special_func = 0;
	window->special_up_func = 0;
	window->mouse_func = 0;
	window->motion_func = 0;
	window->passive_motion_func = 0;
	window->idle_func = 0;

	return window;
}

void destroy_window(Window* window) {
	CHECK_WINDOW(window)

	if (window->title)
		free(window->title);
	window->title = 0;
}

unsigned int get_window_height(Window* window) {
	if (!window) {
		REPORT_ERROR("Invalid window pointer.")
		return 0;
	}

	unsigned int value = 0;

	int id = glutGetWindow();
	glutSetWindow(window->id);
	value = glutGet(GLUT_WINDOW_HEIGHT);
	if (id > 0)
		glutSetWindow(id);

	return value;
}

unsigned int get_window_width(Window* window) {
	if (!window) {
		REPORT_ERROR("Invalid window pointer.")
		return 0;
	}

	unsigned int value = 0;

	int id = glutGetWindow();
	glutSetWindow(window->id);
	value = glutGet(GLUT_WINDOW_WIDTH);
	if (id > 0)
		glutSetWindow(id);

	return value;
}

void set_window_size(Window* window, unsigned int width, unsigned int height) {
	CHECK_WINDOW(window)

	int id = glutGetWindow();
	glutSetWindow(window->id);
	glutReshapeWindow(window->width = width, window->height = height);
	if (id > 0)
		glutSetWindow(id);
}

unsigned int get_window_x_pos(Window* window) {
	if (!window) {
		REPORT_ERROR("Invalid window pointer.")
		return 0;
	}

	unsigned int value = 0;

	int id = glutGetWindow();
	glutSetWindow(window->id);
	value = glutGet(GLUT_WINDOW_X);
	if (id > 0)
		glutSetWindow(id);

	return value;
}

unsigned int get_window_y_pos(Window* window) {
	if (!window) {
		REPORT_ERROR("Invalid window pointer.")
		return 0;
	}

	unsigned int value = 0;

	int id = glutGetWindow();
	glutSetWindow(window->id);
	value = glutGet(GLUT_WINDOW_Y);
	if (id > 0)
		glutSetWindow(id);

	return value;
}

void set_window_position(Window* window, unsigned int x_pos, unsigned int y_pos) {
	CHECK_WINDOW(window)

	int id = glutGetWindow();
	glutSetWindow(window->id);
	glutPositionWindow(window->x_pos = x_pos, window->y_pos = y_pos);
	if (id > 0)
		glutSetWindow(id);
}

bool get_window_fullscreen(Window* window) {
	if (!window) {
		REPORT_ERROR("Invalid window pointer.")
		return false;
	}

	return window->fullscreen;
}

void set_window_fullscreen(Window* window, bool fullscreen) {
	CHECK_WINDOW(window)

	int id = glutGetWindow();
	glutSetWindow(window->id);
	if ((window->fullscreen =  fullscreen)) {
		glutFullScreen();
	} else {
		glutReshapeWindow(window->width, window->height);
		glutPositionWindow(window->x_pos, window->y_pos);
	}
	if (id > 0)
		glutSetWindow(id);
}

void set_window_init_func(Window* window, PFNINITFUNC init_func) {
	CHECK_WINDOW(window)

	window->init_func = init_func;
}

void set_window_display_func(Window* window, PFNDISPLAYFUNC display_func) {
	CHECK_WINDOW(window)

	window->display_func = display_func;
}

void set_window_reshape_func(Window* window, PFNRESHAPEFUNC reshape_func) {
	CHECK_WINDOW(window)

	window->reshape_func = reshape_func;
}

void set_window_keyboard_func(Window* window, PFNKEYBOARDFUNC keyboard_func) {
	CHECK_WINDOW(window)

	window->keyboard_func = keyboard_func;
}

void set_window_keyboard_up_func(Window* window, PFNKEYBOARDUPFUNC keyboard_up_func) {
	CHECK_WINDOW(window)

	window->keyboard_up_func = keyboard_up_func;
}

void set_window_special_func(Window* window, PFNSPECIALFUNC special_func) {
	CHECK_WINDOW(window)

	window->special_func = special_func;
}

void set_window_special_up_func(Window* window, PFNSPECIALUPFUNC special_up_func) {
	CHECK_WINDOW(window)

	window->special_up_func = special_up_func;
}

void set_window_mouse_func(Window* window, PFNMOUSEFUNC mouse_func) {
	CHECK_WINDOW(window)

	window->mouse_func = mouse_func;
}

void set_window_passive_motion_func(Window* window, PFNPASSIVEMOTIONFUNC passive_motion_func) {
	CHECK_WINDOW(window)

	window->passive_motion_func = passive_motion_func;
}

void set_window_idle_func(Window* window, PFNIDLEFUNC idle_func) {
	CHECK_WINDOW(window)

	window->idle_func = idle_func;
}
void set_window_visible(Window* window, bool visible) {
	CHECK_WINDOW(window)

	int id = glutGetWindow();
	glutSetWindow(window->id);
	visible ? glutShowWindow() : glutHideWindow();
	window->visible = visible;
	if (id > 0)
		glutSetWindow(id);
}

